home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
pnm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
419 lines
/*
* $Id: pnm.c,v 0.91 1994/02/20 00:52:48 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* PPM,PGM and PBM related stuff. For space reasons, the PBM is used as
* colormapped images. All PNM should be transitional.
* BUGS: maximum 8-bits per channel
*/
#ifndef NO_PNM
#if !defined(lint) && defined(F_ID)
char *id_ppm = "$Id: pnm.c,v 0.91 1994/02/20 00:52:48 zhao Pre-Release $";
#endif
#include "bit.h"
#include "dmalloc.h"
/********************* Local variables *****************************/
static int pgm; /* pgm==1, PGM */
static int raw = 1; /* default writing */
static long pnm_rlines; /* number of lines read so far */
static int pnm_maxval; /* input data PC resolution */
static float pnm_fnorm = 1.0;
/*******************************************************************
* Identify type and dimension
******************************************************************/
int
PNM_desc(IPTR p)
{
char sig[4];
int err, pbm = 0;
FILE *fp = p->fp;
if (Badfread(sig, 1, 2, fp))
return -1;
/* this should never be true, but if it were, something is really wrong */
if (sig[0] != 'P' || sig[1] < '1' || sig[1] > '6')
{
Bark("PPM_desc", "%s: Not a P{PGB}M file", p->ifile);
return -1;
}
/*
* image dimension and type. If called thru im->desc, type is set
* automatically, but in case pnm_desc is called directly, need to take
* care of im->type here manually, ugly hack
*/
err = (p->w = readpint(fp)) <= 0 || (p->h = readpint(fp)) <= 0;
if ((pgm = (sig[1] == '5' || sig[1] == '2')))
p->type = T_GRAY;
else if ((pbm = (sig[1] == '4' || sig[1] == '1')))
p->type = T_BW;
else
p->type = T_RGBA;
raw = (sig[1] == '6' || sig[1] == '5' || sig[1] == '4');
err = err || (!pbm && ((pnm_maxval = readpint(fp)) <= 0));
/* sanity check */
if (err)
return -1;
if (!pbm && pnm_maxval > PCMAXV)
{
/*
* actually this can be relaxed a little: only RAW file can't be
* handled, the ASCII version is ok with a trivial normalization
*/
Bark("PPM_desc", "%s: maxval>%d not supported", p->ifile, PCMAXV);
return -1;
}
if (!pbm)
{
char pp_[50];
sprintf(pp_, "%s:maxval=%d", raw ? "Raw" : "Ascii", pnm_maxval);
set_iformat_info(p, pp_);
pnm_fnorm = (float) PCMAXV / pnm_maxval;
}
else
{
set_iformat_info(p, raw ? "Raw" : "Ascii");
p->colors = p->cmap->colors = 2; /* fake a colormap */
}
return 0;
}
/* ARGSUSED */
static int
PPM_getrow(FILE * fp, IPTR im, int row, pc_t *in)
{
register pc_t *rgb = in, *rend = rgb + 3 * im->w;
register int err, r, g, b;
if (raw)
{
err = Badfread(rgb, 1, (size_t) 3 * im->w, fp);
}
else
{
for (err = 0; rgb < rend && !err;)
{
if ((r = readpint(fp)) >= 0 &&
(g = readpint(fp)) >= 0 &&
(b = readpint(fp)) >= 0)
{
*rgb++ = r;
*rgb++ = g;
*rgb++ = b;
}
else
err = 1;
}
}
if (err)
{
Bark("PPM_getrow", "%s: Junk found", im->ifile);
return -1;
}
if (pnm_maxval != PCMAXV && pnm_fnorm > 1.1)
{
for (rgb = in; rgb < rend;)
{
*rgb++ = (pnm_fnorm * (*in++));
*rgb++ = (pnm_fnorm * (*in++));
*rgb++ = (pnm_fnorm * (*in++));
}
}
return 0;
}
/* ARGSUSED */
static int
PGM_getrow(FILE * fp, IPTR p, int row, pc_t *in)
{
register pc_t *rgb = in, *rend = rgb + p->w;
register int err = 0, r;
if (raw)
{
err = Badfread(rgb, 1, p->w, fp);
}
else
{
for (; !err && rgb < rend; rgb++)
{
err = ((r = readpint(fp)) < 0);
*rgb = r;
}
}
if (err)
{
Bark("PGM_getrow", "Junk in pixel area");
return -1;
}
if (pnm_maxval != PCMAXV && pnm_fnorm > 1.1)
{
for (rgb = in; rgb < rend; rgb++)
*rgb = (pnm_fnorm * (*in++));
}
return 0;
}
int
PPM_load(IPTR im)
{
register rgba_t *rgba, *rend;
register int j;
int err = 0, h = im->h;
pc_t *tmp, *head;
FILE *fp = im->fp;
pnm_rlines = progress_report(pgm ? "Loading PGM ..." :
"Loading PPM ...", h);
if (!(tmp = head = malloc(sizeof(*tmp) * 3 * im->w)))
return -1;
/*
* get one row at a time and when errors occurs, try not to abort
* completely by returning number of lines read
*/
for (j = 0; j < h && !err; j++)
{
REPORT(j, pnm_rlines);
rgba = ((rgba_t **) im->mraster)[h - 1 - j];
rend = rgba + im->w;
err = (pgm ? PGM_getrow : PPM_getrow) (fp, im, j, head);
if (pgm)
{
for (tmp = head; rgba < rend; rgba++, tmp++)
*rgba = Pack(*tmp, *tmp, *tmp);
}
else
{
for (tmp = head; rgba < rend; rgba++, tmp += 3)
*rgba = Pack(*tmp, *(tmp + 1), *(tmp + 2));
}
}
free(head);
remove_progress_report();
return j;
}
int
PBM_load(IPTR im)
{
register bw_t *ci, *cend;
register int j, bit, k;
int w = im->w, h = im->h;
FILE *fp = im->fp;
int err;
/* fake a colormap with 2 entries in it: 0 white, 1 black */
im->cmap->ct[0][0] = im->cmap->ct[1][0] = im->cmap->ct[2][0] = PCMAXV;
im->cmap->ct[0][1] = im->cmap->ct[1][1] = im->cmap->ct[2][1] = 0;
im->colors = im->cmap->colors = 2; /* fake a colormap */
pnm_rlines = progress_report("Loading PBM ...", h);
for (j = err = 0; j < h; j++)
{
REPORT(j, pnm_rlines);
ci = ((bw_t **) im->mraster)[h - 1 - j];
cend = ci + w;
if (!raw)
{
for (; ci < cend; ci++)
*ci = (readpint(fp) > 0);
err = feof(fp);
}
else
{
for (bit = 0, k = 0; !err && ci < cend; ci++, bit++)
{
if (!(bit &= 7))
k = getc(fp);
err = k == EOF;
*ci = (k & 0x80) ? 1 : 0;
k <<= 1;
}
}
}
#ifdef MDEBUG
M_debug("PBM_load", "Returning j=%d", j);
#endif
remove_progress_report();
return j;
}
int
PBM_dump(IPTR im)
{
register bw_t *ci, *cend;
register int j, k, bit;
int w = im->w, h = im->h;
FILE *fp = im->fp;
pnm_rlines = progress_report("Writing PBM...", h);
fprintf(fp, "%s\n%d %d\n", raw ? "P4" : "P1", w, h);
for (j = 0, k = 1; j < h; j++)
{
REPORT(j, pnm_rlines);
cend = (ci = ((bw_t **) im->mraster)[h - 1 - j]) + w;
if (!raw)
{
for (; ci < cend; ci++, k++)
{
fputs(*ci ? "1 " : "0 ", fp);
if ((k % 34) == 0)
putc('\n', fp);
}
}
else
{
for (bit = 0, k = 0; ci < cend; ci++)
{
k = (k << 1) | *ci;
if (++bit == 8)
{
putc(k, fp);
bit = k = 0;
}
}
if (bit)
{
k <<= (8 - bit);
putc(k, fp);
}
}
}
if (!raw)
putc('\n', fp);
remove_progress_report();
return (fflush(fp)) ? -1 : 0;
}
int
PPM_dump(IPTR im)
{
register rgba_t *rgba, *rend;
register int r, g, b;
register int j, k;
int w = im->w, h = im->h;
const char *s;
FILE *fp = im->fp;
pgm = (im->type == T_GRAY);
pnm_rlines = progress_report(pgm ? "Writing PGM..." : "Writing PPM...", h);
s = pgm ? (raw ? "P5" : "P2") : (raw ? "P6" : "P3");
fprintf(fp, "%s\n%d %d\n%d\n", s, w, h, PCMAXV);
for (j = 0, k = 1; j < h; j++)
{
REPORT(j, pnm_rlines);
rend = (rgba = ((rgba_t **) im->mraster)[h - 1 - j]) + w;
if (pgm)
{
for (; rgba < rend; rgba++, k++)
{
r = (*rgba) & PCMAXV;
if (!raw)
{
fprintf(fp, "% 3d", r);
if ((k % 17) == 0)
putc('\n', fp);
}
else
putc(r, fp);
}
}
else
{
for (; rgba < rend; rgba++, k++)
{
CPACK2RGB(*rgba, r, g, b);
if (raw)
{
putc(r, fp);
putc(g, fp);
putc(b, fp);
}
else
{
fprintf(fp, "%4d%4d%4d ", r, g, b);
if ((k % 5) == 0)
putc('\n', fp);
}
}
}
}
if (!raw)
putc('\n', fp);
remove_progress_report();
return (fflush(fp)) ? -1 : im->h;
}
/* ARGSUSED */
const char *
PPM_wdefault(const IPTR im)
{
return raw ? "Raw" : "Ascii";
}
/* utility function for setting raw output */
void
set_pnm_raw(int y)
{
raw = y;
}
/* ARGSUSED */
int
PPMdump_init(IPTR im)
{
return (raw = !raw);
}
#endif